/*
 * Vulnerability detector: Debian EVR version matching functions
 * Piece of code extracted from Debian DPKG and RPM rpmLib source code.
 * Copyright (C) 2015-2020, Wazuh Inc.
 * February 20th, 2020.
 *
 * This program is free software; you can redistribute it
 * and/or modify it under the terms of the GNU General Public
 * License (version 2) as published by the FSF - Free Software
 * Foundation.
 */

#ifndef CLIENT

#ifndef WM_VULNDETECTOR_EVR
#define WM_VULNDETECTOR_EVR

#define DPKG_BIT(n) (1UL << (n))
#define C_CTYPE_BIT(bit)    (1 << (bit))

enum c_ctype_bit {
    C_CTYPE_BLANK = C_CTYPE_BIT(0),
    C_CTYPE_WHITE = C_CTYPE_BIT(1),
    C_CTYPE_SPACE = C_CTYPE_BIT(2),
    C_CTYPE_UPPER = C_CTYPE_BIT(3),
    C_CTYPE_LOWER = C_CTYPE_BIT(4),
    C_CTYPE_DIGIT = C_CTYPE_BIT(5),

    C_CTYPE_ALPHA = C_CTYPE_UPPER | C_CTYPE_LOWER,
    C_CTYPE_ALNUM = C_CTYPE_ALPHA | C_CTYPE_DIGIT,
};

/**
 * Enum constants for the supported relation operations that can be done.
 */
enum pkg_relation {
    /** The “none” relation, sentinel value. */
    PKG_RELATION_NONE  = 0,
    /** Equality relation (‘=’). */
    PKG_RELATION_EQ    = DPKG_BIT(0),
    /** Less than relation (‘<<’). */
    PKG_RELATION_LT    = DPKG_BIT(1),
    /** Less than or equal to relation (‘<=’). */
    PKG_RELATION_LE    = PKG_RELATION_LT | PKG_RELATION_EQ,
    /** Greater than relation (‘>>’). */
    PKG_RELATION_GT    = DPKG_BIT(2),
    /** Greater than or equal to relation (‘>=’). */
    PKG_RELATION_GE    = PKG_RELATION_GT | PKG_RELATION_EQ,
};

/**
 * Enum constants for the supported package types comparisions.
 */
typedef enum {
    VER_TYPE_NONE  = 0,
    VER_TYPE_DEB,
    VER_TYPE_RPM,
    VER_TYPE_RPM_CENTOS,
    VER_TYPE_NVD,
} version_type;

/**
 * Data structure representing a version.
 */
struct pkg_version {
    /** The epoch. It will be zero if no epoch is present. */
    int epoch;
    /** The upstream part of the version. */
    const char *version;
    /** The revision part of the version. */
    const char *revision;
};

bool c_isbits(int c, enum c_ctype_bit bits);
bool c_isdigit(int c);
bool c_isalpha(int c);
int order(int c);
int pkg_version_compare(const struct pkg_version *a, const struct pkg_version *b);
bool pkg_version_relate(const struct pkg_version *a, enum pkg_relation rel, const struct pkg_version *b, version_type vertype);

#endif
#endif
